#pragma once
#include "../comm/JsonUtil.hpp"
#include "../comm/LOG.hpp"
#include "../comm/UUIDUtil.hpp"
#include "fields.hpp"
#include "abstract.hpp"
#include <vector>

using namespace ns_rpc;
using namespace ns_json;
using namespace ns_fields;
using namespace ns_LOG;
namespace ns_msg
{
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;

        virtual std::string serialize() override
        {
            std::string body;
            bool ret = JsonUtil::serialize(_val, body);
            if (ret == false)
                std::string();
            return body;
        }
        virtual bool unserialize(const std::string& body) override
        {
            bool ret = JsonUtil::unserialize(body, _val);
            return ret;
        }
    protected:
        Json::Value _val;
    };

    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;

        virtual bool check() override
        {
            if (_val[KEY_METHOD].isNull() == true || _val[KEY_METHOD].isString() == false)
            {
                LOG(ERROR, "Rpc请求方法名称为空 或者 请求方法名称类型错误!!!");
                return false;
            }
            else if (_val[KEY_PARAMETERS].isNull() == true || _val[KEY_PARAMETERS].isObject() == false)
            {
                LOG(ERROR, "Rpc请求方法参数为空 或者 方法参数类型错误!!!");
                return false;
            }
            return true;
        }
        std::string GetMethod()
        {
            return _val[KEY_METHOD].asString();
        }
        void SetMethod(const std::string &method)
        {
            _val[KEY_METHOD] = method;
        }
        Json::Value GetParameters()
        {
            return _val[KEY_PARAMETERS];
        }
        void SetParameters(const Json::Value &para)
        {
            _val[KEY_PARAMETERS] = para;
        }
    };

    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;

        virtual bool check() override
        {
            if (_val[KEY_TOPIC_KEY].isNull() == true || _val[KEY_TOPIC_KEY].isString() == false)
            {
                LOG(ERROR, "主题请求名称为空 或者 名称类型错误!!!");
                return false;
            }
            else if (_val[KEY_OTYPE].isNull() == true || _val[KEY_OTYPE].isIntegral() == false)
            {
                LOG(ERROR, "主题请求操作方式为空 或者 操作类型错误!!!");
                return false;
            }

            // 特判publish，主题发布才需要消息检测,服务端的TopicResponse不需要进行处理，只转发给其他客户端
            else if (_val[KEY_OTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH &&
                     (_val[KEY_TOPIC_MESSAGE].isNull() == true || _val[KEY_TOPIC_MESSAGE].isString() == false))
            {
                LOG(ERROR, "主题发布内容为空 或者 内容类型错误");
                return false;
            }

            return true;
        }
        std::string GetKey()
        {
            return _val[KEY_TOPIC_KEY].asString();
        }
        void SetKey(const Json::Value &val)
        {
            _val[KEY_TOPIC_KEY] = val;
        }
        // 类型在枚举类中
        TopicOptype GetOtype()
        {
            return (TopicOptype)_val[KEY_OTYPE].asInt();
        }
        void SetOtype(const TopicOptype otype)
        {
            _val[KEY_OTYPE] = (int)otype;
        }
        std::string GetMessage()
        {
            return _val[KEY_TOPIC_MESSAGE].asString();
        }
        void SetMessage(const std::string msg)
        {
            _val[KEY_TOPIC_MESSAGE] = msg;
        }
    };

    using Address = std::pair<std::string, int>;

    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        
        virtual bool check() override
        {
            if (_val[KEY_METHOD].isNull() == true || _val[KEY_METHOD].isString() == false)
            {
                LOG(ERROR, "服务请求方法名称为空 或者 名称类型错误!!!");
                return false;
            }
            else if (_val[KEY_OTYPE].isNull() == true || _val[KEY_OTYPE].isIntegral() == false)
            {
                LOG(ERROR, "服务请求操作方式为空 或者 操作类型错误!!!");
                return false;
            }

            //不包括服务发现的前提下 (因为服务端的服务发现 没有Host字段)
            else if (_val[KEY_OTYPE].asInt() != (int)ServiceOptype::SERVICE_DISCOVER && (_val[KEY_HOST].isNull() == true || _val[KEY_HOST].isObject() == false || _val[KEY_HOST][KEY_HOST_IP].isNull() == true || _val[KEY_HOST][KEY_HOST_IP].isString() == false || _val[KEY_HOST][KEY_HOST_PORT].isNull() == true || _val[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                LOG(ERROR, "服务的主机信息错误!!!");
                return false;
            }
            return true;
        }
        std::string GetMethod()
        {
            return _val[KEY_METHOD].asString();
        }
        void SetMethod(const std::string &method)
        {
            _val[KEY_METHOD] = method;
        }
        // 类型在枚举类中
        ServiceOptype GetOtype()
        {
            return (ServiceOptype)_val[KEY_OTYPE].asInt();
        }
        void SetOtype(const ServiceOptype otype)
        {
            _val[KEY_OTYPE] = (int)otype;
        }
        Address GetHost()
        {
            Address addr;
            addr.first = _val[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _val[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }

        void SetHost(const Address &addr)
        {
            Json::Value val;
            val[KEY_HOST_IP] = addr.first;
            val[KEY_HOST_PORT] = addr.second;
            _val[KEY_HOST] = val;
        }
    };


    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        virtual bool check() override
        {
            //在响应中，大部分的响应都只有响应状态码
            //因此只需要判断响应状态码字段是否存在，类型是否正确即可
            if (_val[KEY_RCODE].isNull() == true) {
                LOG(ERROR,"响应中没有响应状态码!!!");
                return false;
            }
            if (_val[KEY_RCODE].isIntegral() == false) {
                LOG(ERROR,"响应状态码类型错误!!!");
                return false;
            }
            return true;
            
        }
        virtual Rcode GetRcode()
        {
            return (Rcode)_val[KEY_RCODE].asInt();
        }
        virtual void SetRcode(const Rcode rcode)
        {
            _val[KEY_RCODE] = (int)rcode;
        }
    };

    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;

        virtual bool check() override
        {
            if(_val[KEY_RCODE].isNull() == true || _val[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR,"Rpc响应码为空 或者 响应码类型错误!!!");
                return false;
            }
            if(_val[KEY_RESULT].isNull() == true)
            {
                LOG(ERROR,"Json回应结果为空 或者 回应结果类型错误!!!");
                return false;
            }
            return true;
        }

        Json::Value GetResult()
        {
            return _val[KEY_RESULT];
        }
        void SetResult(const Json::Value &res)
        {
            _val[KEY_RESULT] = res;
        }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        virtual bool check() override
        {
            if(_val[KEY_RCODE].isNull() == true || _val[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR,"Topic响应码为空 或者 响应码类型错误!!!");
                return false;
            }
            return true;
        }

    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            if(_val[KEY_RCODE].isNull() == true|| _val[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR,"服务响应码为空 或者 响应码类型错误!!!");
                return false;
            }
            else if(_val[KEY_OTYPE].isNull() == true || _val[KEY_OTYPE].isIntegral() == false)
            {
                LOG(ERROR,"服务操作为空 或者 服务操作类型错误!!!");  
                return false;          
            }
            //服务发现的前提下 客户端服务发现需要Host
            else if(_val[KEY_OTYPE].asInt() == (int)ServiceOptype::SERVICE_DISCOVER && (
                _val[KEY_METHOD].isNull() == true || _val[KEY_METHOD].isString() == false 
                ||_val[KEY_HOST].isNull() == true || _val[KEY_HOST].isArray() == false
                
            ) )
            {
                LOG(ERROR,"服务发现响应失败!!!");
                return false;
            }
            return true;
        }

        ServiceOptype GetOtype()
        {
            return (ServiceOptype)_val[KEY_OTYPE].asInt();
        }
        void SetOtype(const ServiceOptype& otype)
        {
            _val[KEY_OTYPE] = (int)otype;
        }
        std::string GetMethod()
        {
            return _val[KEY_METHOD].asString();
        }
        void SetMethod(const std::string &method)
        {
            _val[KEY_METHOD] = method;
        }
        std::vector<Address> GetHosts()
        {
            std::vector<Address> addrs;
            for(int i = 0;i<_val[KEY_HOST].size();i++)
            {
                Address addr;
                //相当于vecotr<unordered_map<string,int>>
                addr.first = _val[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _val[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.push_back(addr);
            }
            return addrs;
        }
        void SetHosts(const std::vector<Address> addrs)
        {
            for(auto& e : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = e.first;
                val[KEY_HOST_PORT] = e.second;
                //Json里数组类型要append
                _val[KEY_HOST].append(val);
            }
        }
    };

    //实现一个消息对象的生产工厂
    class MessageFactory
    {
    public:
        // 因为要返回不同种对象指针，所以返回值采用父类统一返回
        static BaseMessage::ptr Createmsg(Mtype mtype)
        {
            switch(mtype)
            {
                case Mtype::RPC_REQ : return std::make_shared<RpcRequest>();
                case Mtype::RPC_RES : return std::make_shared<RpcResponse>();
                case Mtype::TOPIC_REQ : return std::make_shared<TopicRequest>();
                case Mtype::TOPIC_RES : return std::make_shared<TopicResponse>();
                case Mtype::SERVICE_REQ : return std::make_shared<ServiceRequest>();
                case Mtype::SERVICE_RES : return std::make_shared<ServiceResponse>();
                //空的智能指针对象
                default: return BaseMessage::ptr();
            }
            
        }

        //函数可变参数模板模板
        //这里可以根据参数直接返回对应类型的shared_ptr
        template<class T,class ...Args>
        static std::shared_ptr<T> Createmsg(Args&& ...args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };


}
